/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;

import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.DateUtils;
import com.comac.ins.common.core.utils.StringUtils;
import com.comac.ins.common.core.utils.file.FileUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.constant.IsfdMeshModelConstants;
import com.comac.ins.isfd.constant.IsfdMeshOp2Constants;
import com.comac.ins.isfd.constant.enums.IsfdMeshOp2BoStatusEnum;
import com.comac.ins.isfd.constant.enums.IsfdMongoQueryLogicalOperatorEnum;
import com.comac.ins.isfd.constant.enums.IsfdMongoQueryOperatorEnum;
import com.comac.ins.isfd.constant.enums.PartFileSizeUnitEnum;
import com.comac.ins.isfd.domain.IsfdDatabaseMongoQuery;
import com.comac.ins.isfd.domain.bo.IsfdMeshQueryBo;
import com.comac.ins.isfd.domain.vo.IsfdMeshModelStructureDefinitionVo;
import com.comac.ins.isfd.rpc.simright.SimrightRpcUtils;
import com.comac.ins.isfd.rpc.simright.constants.enums.SimrightTaskStatusEnum;
import com.comac.ins.isfd.service.IIsfdDatabaseMongoService;
import com.comac.ins.isfd.service.IIsfdMeshModelStructureDefinitionService;
import com.comac.ins.isfd.service.IIsfdMeshOp2Service;
import com.comac.ins.system.service.ISysDictDataService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * 自然网格结果service业务处理
 *
 * @author hxloongs
 * @date 2025-03-24
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class IsfdMeshOp2ServiceImpl implements IIsfdMeshOp2Service {
    @Autowired
    private IIsfdDatabaseMongoService mongoService;

    @Autowired
    private ISysDictDataService iSysDictDataService;

    @Autowired
    private IIsfdMeshModelStructureDefinitionService iIsfdMeshModelStructureDefinitionService;

    @Autowired
    private SimrightRpcUtils simrightRpcUtils;

    @Override
    public TableDataInfo<Document> queryList(IsfdMeshQueryBo query) {
        PageQuery pageQuery = query.getPageQuery();
        String modelNumber = query.getModelNumber();
        String sectionNumber = query.getSectionNumber();
        String sectionNumbers = query.getSectionNumbers();
        String batchNumber = query.getBatchNumber();
        String roundNumber = query.getRoundNumber();
        Integer status = query.getStatus();
        String fileName = query.getFileName();
        Date uploadTimeStartTime = query.getUploadTimeStartTime();
        Date uploadTimeEndTime = query.getUploadTimeEndTime();
        List<IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition> conditions = new ArrayList<>();
        if (StringUtils.isNotBlank(modelNumber)) {
            IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition operationModel = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
            operationModel.setOperator(IsfdMongoQueryOperatorEnum.EQUAL.getValue());
            operationModel.setValue(modelNumber);
            operationModel.setFieldName("modelNumber");
            conditions.add(operationModel);
        }
        if (StringUtils.isNotBlank(sectionNumber)) {
            IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition operationSection = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
            operationSection.setOperator(IsfdMongoQueryOperatorEnum.LIKE.getValue());
            operationSection.setValue(sectionNumber);
            operationSection.setFieldName("sectionNumbers");
            conditions.add(operationSection);
        }
        if (StringUtils.isNotBlank(sectionNumbers)) {
            String[] sectionNumberArray = sectionNumbers.split(",");
            for (String sectionNum : sectionNumberArray) {
                IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition operationSection = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
                operationSection.setOperator(IsfdMongoQueryOperatorEnum.LIKE.getValue());
                operationSection.setValue(sectionNum);
                operationSection.setFieldName("sectionNumbers");
                operationSection.setLogicalOperator(IsfdMongoQueryLogicalOperatorEnum.OR.getValue());
                conditions.add(operationSection);
            }
        }
        if (StringUtils.isNotBlank(batchNumber)) {
            IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition operationBatch = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
            operationBatch.setOperator(IsfdMongoQueryOperatorEnum.EQUAL.getValue());
            operationBatch.setValue(batchNumber);
            operationBatch.setFieldName("batchNumber");
            conditions.add(operationBatch);
        }
        if (StringUtils.isNotBlank(roundNumber)) {
            IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition operationRound = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
            operationRound.setOperator(IsfdMongoQueryOperatorEnum.EQUAL.getValue());
            operationRound.setValue(roundNumber);
            operationRound.setFieldName("roundNumber");
            conditions.add(operationRound);
        }

        if (status != null) {
            IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition operationStatus = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
            operationStatus.setOperator(IsfdMongoQueryOperatorEnum.EQUAL.getValue());
            operationStatus.setValue(String.valueOf(status));
            operationStatus.setFieldName("status");
            operationStatus.setValueNumberCheck(Boolean.TRUE);
            conditions.add(operationStatus);
        }

        if (StringUtils.isNotBlank(fileName)) {
            IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition operationFileName = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
            operationFileName.setOperator(IsfdMongoQueryOperatorEnum.LIKE.getValue());
            operationFileName.setValue(fileName);
            operationFileName.setFieldName("fileName");
            conditions.add(operationFileName);
        }
        if (uploadTimeStartTime != null && uploadTimeEndTime != null) {
            long uploadTimeEndTimeTime = uploadTimeEndTime.getTime();
            IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition operationBatchEnd = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
            operationBatchEnd.setOperator(IsfdMongoQueryOperatorEnum.LESS_THAN_EQUALS.getValue());
            operationBatchEnd.setValue(String.valueOf(uploadTimeEndTimeTime));
            operationBatchEnd.setFieldName("uploadTime");
            long uploadTimeStartTimeTime = uploadTimeStartTime.getTime();
            IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition operationBatchBegin = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
            operationBatchBegin.setOperator(IsfdMongoQueryOperatorEnum.GREATER_THAN_EQUALS.getValue());
            operationBatchBegin.setValue(String.valueOf(uploadTimeStartTimeTime));
            operationBatchBegin.setFieldName("uploadTime");
            conditions.add(operationBatchEnd);
            conditions.add(operationBatchBegin);
        }
        IsfdDatabaseMongoQuery queryCondition = new IsfdDatabaseMongoQuery();
        queryCondition.setConditions(conditions);
        pageQuery.setOrderByColumn("uploadTime");
        queryCondition.setPageQuery(pageQuery);

        // 查询结果
        Long totalCount = mongoService.count(getMeshModelTableName(), queryCondition);
        List<Document> result = mongoService.aggregationQuery(getMeshModelTableName(), queryCondition);
        result.forEach(doc -> {
            Long uploadTime = doc.getLong("uploadTime");
            doc.put("uploadTimeStr", DateUtils.parseDateToLong(DateUtils.YYYY_MM_DD_HH_MM_SS, uploadTime));

            String fileSize = String.valueOf(doc.get("fileSize"));
            doc.put("fileSizeWithUnit", PartFileSizeUnitEnum.getFileSizeWithUnit(Long.valueOf(fileSize)));

            String targetModelNumber = String.valueOf(doc.get("modelNumber"));
            String location = targetModelNumber + "-" + doc.getString("batchNumber");
            // 处理sectionNames
            StringJoiner sectionJoiner = new StringJoiner("、", "[", "]");
            if (StringUtils.isNotBlank(doc.getString("sectionNumbers"))) {
                Arrays.stream(doc.getString("sectionNumbers").split(","))
                    .map(String::trim)
                    .filter(StringUtils::isNotBlank)
                    .forEach(targetSectionNumber -> {
                        IsfdMeshModelStructureDefinitionVo sectionVo = iIsfdMeshModelStructureDefinitionService
                            .queryOneByQueryIndex(targetModelNumber, targetSectionNumber, null);
                        if (sectionVo != null && StringUtils.isNotBlank(sectionVo.getName())) {
                            sectionJoiner.add(sectionVo.getName());
                        }
                    });
            }
            doc.put("location", location + "-" + sectionJoiner.toString());
            // 增加对数巧解析任务状态的查询
            String parser = doc.getString("parser");
            if (IsfdMeshModelConstants.MESH_OP2_PARSER_SIMRIGHT.equalsIgnoreCase(parser)) {
                String parseTaskId = doc.getString("parseTaskId");
                if (StringUtils.isBlank(parseTaskId)){
                    log.error("数巧解析任务id为空，uploadId: {}", doc.get("uploadId"));
                } else {
                    updateOp2ParseStatusBySimrightTask(parseTaskId, doc);
                }
            }


        });
        return TableDataInfo.build(result, totalCount);
    }

    private void updateOp2ParseStatusBySimrightTask(String parseTaskId, Document doc){
        try {
            SimrightTaskStatusEnum taskStatus = simrightRpcUtils.queryConverTask(parseTaskId);
            if(taskStatus == null) {
                throw new BaseException("数巧解析查询错误：未知任务状态");
            }
            if (taskStatus.equals(SimrightTaskStatusEnum.SUCCESS)){
                updateStatusByParseTaskId(parseTaskId, IsfdMeshOp2BoStatusEnum.STRUCTURE_SUCCESS, null);
                doc.put("status",IsfdMeshOp2BoStatusEnum.STRUCTURE_SUCCESS.getValue());
            } else if (taskStatus.equals(SimrightTaskStatusEnum.FAILURE)) {
                updateStatusByParseTaskId(parseTaskId, IsfdMeshOp2BoStatusEnum.STRUCTURE_FAILURE, "数巧解析文件失败");
                doc.put("status",IsfdMeshOp2BoStatusEnum.STRUCTURE_FAILURE.getValue());
            }
        } catch (Exception e){
            String msg = e.getMessage();
            if (msg == null) msg = e.toString();
            if (msg.length() > 200) msg = msg.substring(0, 200) + "...";
            String errorMessage = "查询数巧解析任务出现错误，message：" + msg;
            log.error(errorMessage);
        }
    }

    private void updateStatusByParseTaskId(String parseTaskId, IsfdMeshOp2BoStatusEnum status, String message) {
        // 查询数据
        String collectionName = getMeshModelTableName();
        IsfdDatabaseMongoQuery mongoQuery = new IsfdDatabaseMongoQuery();
        IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition queryCondition = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
        queryCondition.setFieldName("parseTaskId");
        queryCondition.setOperator("eq");
        queryCondition.setValue(parseTaskId);
        mongoQuery.setConditions(List.of(queryCondition));

        Document updateDoc = new Document();
        updateDoc.put("status", status.getValue());
        updateDoc.put("message", message);

        mongoService.update(collectionName, mongoQuery, updateDoc);
    }

    @Override
    public void download(String id, HttpServletResponse response) {
        Document document = mongoService.findById(getMeshModelTableName(), id);
        if (document == null) {
            throw new BaseException("未找到文件！");
        }
        Path filePath = Paths.get(document.getString("fileUrl"));
        // 确保文件存在
        if (!Files.exists(filePath)) {
            throw new BaseException("未找到文件！");
        }

        FileUtils.setAttachmentResponseHeader(response, filePath.getFileName().toString());
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8");

        // 写入文件内容到响应
        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(filePath.toFile()))) {
            response.setContentLengthLong(Files.size(filePath));
            IOUtils.copy(in, response.getOutputStream());
            response.flushBuffer();
        } catch (Exception e) {
            log.error("写出文件报错", e);
            throw new BaseException("写出文件报错");
        }
    }

    /**
     * 获取表名称
     */
    public String getMeshModelTableName() {
        String tableName = iSysDictDataService.selectDictValueByTypeAndLabel(IsfdMeshModelConstants.MODEL_MESH, IsfdMeshOp2Constants.MESH_OP2_TABLE_NAME);
        return StringUtils.isNotBlank(tableName) ? tableName : IsfdMeshOp2Constants.DEFAULT_MESH_OP2_TABLE_NAME;
    }
}
